﻿using System;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Reflection;
using ServerLib;
using System.Resources;
using monitor_2_DBwork;

namespace monitor_server_2
{
    
    public partial class Main : Form
    {
        //Формы
        MyForm _accessListForm = new MyForm();
        MyForm _deviceListForm = new MyForm();
        MyForm _trustedAddressListForm = new MyForm();
        MyForm _serverLogForm = new MyForm();

        private const bool CheckHard = false;
        
        public static ResourceManager Rm = new ResourceManager(typeof(monitor_server_2_r));

        private readonly Bitmap _animatedImage;// = new Bitmap("Resources\\loading.gif");
        //readonly Bitmap _animatedImage = new Bitmap(Rm.GetObject("loading"));
        Boolean _currentlyAnimating;
        private bool _animateLoading = true;
        private readonly string _success;

        private delegate void ItemEnableDelegate();

        private delegate void LoadingCompleteDelegate(bool dbConnected);

        private delegate bool CheckDBConnectionDelegate();

        public void AnimateImage()
        {
            if (!_currentlyAnimating)
            {
                //Begin the animation only once.
                ImageAnimator.Animate(_animatedImage, OnFrameChanged);
                _currentlyAnimating = true;
            }
        }

        private void OnFrameChanged(object o, EventArgs e)
        {
            Invalidate();
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            if (!_animateLoading)
                return;
            //Begin the animation.
            AnimateImage();

            //Get the next frame ready for rendering.
            ImageAnimator.UpdateFrames();

            //Draw the next frame in the animation.
            e.Graphics.DrawImage(_animatedImage, new Point(0, 0));
        }

        public Main()
        {
            InitializeComponent();
            if (!File.Exists("Resources\\loading.gif"))
            {
                _success = "loading.gif";
                return;
            }

            const string file = "Resources\\prog.ico";
            if (!File.Exists(file))
            {
                _success = "prog.ico";
                return;
            }

            _success = "ok";
            _animatedImage = new Bitmap("Resources\\loading.gif");
            var d = new CheckDBConnectionDelegate(CheckCon);
            d.BeginInvoke(CheckConCallback, d);
            Visible = true;
            notify1.Visible = false;
        }

        private void Form1_Load(object sender, EventArgs e)
        {

            //var checker = new ClientsChecker();
            //checker.CheckClient(new byte[0]);

            Curdir.CurDir = Directory.GetCurrentDirectory();

            //Иконки
            Icon = new Icon(@"resources\prog.ico");
            notify1.Icon = new Icon(@"resources\prog.ico");
            notify1.Text = Rm.GetString("IconName");

            //notify1.Visible = true;
            notify1.MouseClick += notify1_MouseClick;

            //Контекстное меню
            contextMenu.BackColor = Color.AliceBlue;
            //contextMenu.Items.Add("GetStatus");
            //contextMenu.Items.Add("Запустить сервер");
            contextMenu.Items.Add("Остановить сервер");
            contextMenu.Items.Add("Открыть список доступа");
            contextMenu.Items.Add("Открыть список устройств");
            contextMenu.Items.Add("Открыть список доверенных адресов");
            contextMenu.Items.Add("Открыть журнал событий");
            contextMenu.Items.Add(new ToolStripSeparator());
            contextMenu.Items.Add("Выход");
            contextMenu.DefaultDropDownDirection = ToolStripDropDownDirection.AboveLeft;
            
            notify1.ContextMenuStrip = contextMenu;

            contextMenu.ItemClicked += contextmenu_ItemClicked;

            //var d = new CheckDBConnectionDelegate(CheckCon);
            //d.BeginInvoke(CheckConCallback, d);

            Resize += FormForTray_Resize;
        }

        bool CheckCon()
        {
            try
            {
                return DBwork.CheckConnection();
            }
            catch (Exception ex)
            {
                var str = new StringBuilder();
                str.Append(ex.Message);
                if (ex.InnerException != null)
                    str.Append("\r\n" + ex.InnerException.Message);
                try
                {
                    File.WriteAllText("ErrorLog.txt", "\r\n\r\n--- " + DateTime.Now.ToShortDateString() + " " + DateTime.Now.ToShortTimeString() + " ---\r\n" + str);
                }
                catch (Exception)
                {
                }
                MessageBox.Show(str.ToString());
                throw; 
                return false;
            }
            
        }

        void CheckConCallback(IAsyncResult iar)
        {
            var ar = (CheckDBConnectionDelegate)iar.AsyncState;
            var res = ar.EndInvoke(iar);
            _animateLoading = false;
            //contextMenu.Items[0].PerformClick();
            if (!res)
                MessageBox.Show(Rm.GetString("NoDBConnection") + "\r\n" + Rm.GetString("ProgramWillBeClosed"), Rm.GetString("Error"), MessageBoxButtons.OK, MessageBoxIcon.Error);
            var d = new LoadingCompleteDelegate(OnLoadingComplete);
            Invoke(new LoadingCompleteDelegate(d), res);
        }

        void OnLoadingComplete(bool dbConnected)
        {
            if (!dbConnected)
                Close();
            string board = "ok";
            if (CheckHard)
            {
                board = HardIdentifier.CheckBinding();
                if (board != "ok")
                {
                    MessageBox.Show(Rm.GetString("Error") + ".\r\n" + board.Remove(0, 4), Rm.GetString("Error"),
                                    MessageBoxButtons.OK, MessageBoxIcon.Error);
                    Close();
                }
            }
            if((board == "ok"))
            {
                //StartStopServerDelegate d = EnableServerItem;
                //StartStopServerEvent += d;
                //var sd = new ServerStartDelegate(ServerStart);
                //contextMenu.Items[0].Enabled = false;
                //sd.BeginInvoke(notify1, ServerFirstStartCallback, sd);
                var str = ServerStart(notify1);
                if (str != "ok")
                {
                    MessageBox.Show(str.Substring(4), Rm.GetString("Error"), MessageBoxButtons.OK, MessageBoxIcon.Stop,
                                    MessageBoxDefaultButton.Button1);
                    contextMenu.Items[0].Text = @"Запустить сервер";
                }

                //StartServerClicked();

                notify1.Visible = true;
                WindowState = FormWindowState.Minimized;
                notify1.ShowBalloonTip(2000, "", Rm.GetString("LoadingComplete") ?? "resources error",
                                       ToolTipIcon.Info);
            }
        }

        private delegate string ServerStartDelegate(NotifyIcon icon);

        private delegate string ServerStopDelegate();

        private string ServerStart(NotifyIcon icon)
        {
            return Server.ServerStart(null);
        }

        private void StartServerClicked()
        {
            var sd = new ServerStartDelegate(ServerStart);
            contextMenu.Items[0].Enabled = false;
            sd.BeginInvoke(notify1, ServerStartCallback, sd);
        }

        private void ServerStartCallback(IAsyncResult iar)
        {
            var ar = (ServerStartDelegate) iar.AsyncState;
            var res = ar.EndInvoke(iar);
            if (res != "ok")
            {
                MessageBox.Show(res.Substring(4), Rm.GetString("Error"), MessageBoxButtons.OK, MessageBoxIcon.Stop, MessageBoxDefaultButton.Button1);
            }
            else
            {
                contextMenu.Items[0].Text = @"Остановить сервер";
            }

            ServerItemEnable();
            //OnStartStopServerEvent(false);


        }

        private string ServerStop()
        {
            return Server.ServerStop();
        }

        private void ServerStopCallback(IAsyncResult iar)
        {
            var ar = (ServerStopDelegate)iar.AsyncState;
            var res = ar.EndInvoke(iar);
            if (res != "ok")
            {
                MessageBox.Show(res.Substring(4), Rm.GetString("Error"), MessageBoxButtons.OK, MessageBoxIcon.Stop, MessageBoxDefaultButton.Button1);
            }
            else
            {
                contextMenu.Items[0].Text = Rm.GetString("StartServer");
            }
            ServerItemEnable();
            //OnStartStopServerEvent(true);
        }

        void contextmenu_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {
            switch (e.ClickedItem.Text)
            {

                #region test

                case "GetStatus":
                    //DBwork.Test();
                    Server.Test();
                    break;

                #endregion

                #region Запустить сервер

                case "Запустить сервер":
                    //var sd = new ServerStartDelegate(ServerStart);
                    //e.ClickedItem.Enabled = false;
                    //sd.BeginInvoke(notify1, ServerStartCallback, sd);
                    StartServerClicked();

                    //var ret = Server.ServerStart(notify1);
                    //if (ret.Contains("err:"))
                    //{
                    //    MessageBox.Show(ret.Substring(4), Rm.GetString("Error"), MessageBoxButtons.OK, MessageBoxIcon.Stop, MessageBoxDefaultButton.Button1);
                    //    return;
                    //}
                    //e.ClickedItem.Text = "Остановить сервер";
                    
                    
                    //string str = DBwork.Test();
                    //str = DBwork.CallMethod("MakeXML", "all", @"d:\test.xml");
                    //str = DBwork.CallMethod("DelUser", "Can't");
                    //var str = DBwork.CallMethod("CheckPassword", "testLogin", "testPassword");
                    //var str1 = DBwork.CallMethod("GetUsers");
                    //DBwork.Test();
                    //str = DBwork.AddUser("just", "said", "that");
                    //string a = DBwork.CheckPassword("Waka", "Flocka");
                    //var tree = DBwork.GetTree();

                    break;

                #endregion

                #region Остановить сервер

                case "Остановить сервер":
                    var sStop = new ServerStopDelegate(ServerStop);
                    e.ClickedItem.Enabled = false;
                    sStop.BeginInvoke(ServerStopCallback, sStop);


                    //e.ClickedItem.Text = Rm.GetString("StartServer");
                    //Server.ServerStop();
                    break;

                #endregion

                #region Список доступа

                case "Открыть список доступа":
                    if (_accessListForm.IsNull)
                    {
                        Form newAccessListForm = new AccessList();
                        newAccessListForm.Owner = this;
                        _accessListForm = new MyForm(newAccessListForm);
                        //AccessListForm.SetForm = newAccessListForm;
                    }
                    else
                        _accessListForm.Show();
                    break;

                #endregion

                #region Список устройств

                case "Открыть список устройств":
                    if (_deviceListForm.IsNull)
                    {
                        Form newDeviceListForm = new DeviceList();
                        newDeviceListForm.Owner = this;
                        _deviceListForm = new MyForm(newDeviceListForm);
                        //AccessListForm.SetForm = newAccessListForm;
                    }
                    else
                        _deviceListForm.Show();
                    break;

                #endregion

                #region Список доверенных адресов

                case "Открыть список доверенных адресов":

                    if (_trustedAddressListForm.IsNull)
                    {
                        Form newtrustedAddressListForm = new TrustedAddressList();
                        newtrustedAddressListForm.Owner = this;
                        _trustedAddressListForm = new MyForm(newtrustedAddressListForm);
                        //AccessListForm.SetForm = newAccessListForm;
                    }
                    else
                        _trustedAddressListForm.Show();

                    break;

                #endregion

                #region Журнал событий сервера

                case "Открыть журнал событий":
                    if (_serverLogForm.IsNull)
                    {
                        Form newServerLogForm = new ServerLog();
                        newServerLogForm.Owner = this;
                        _serverLogForm = new MyForm(newServerLogForm);
                        //AccessListForm.SetForm = newAccessListForm;
                    }
                    else
                        _serverLogForm.Show();
                    break;

                #endregion

                case "Выход":
                    Server.ServerStop();
                    //Server.WriteToLog(Rm.GetString("ServerClosed"), ServerCategories.Info, false);
                    Close();
                    break;
            }
        }

        void ServerItemEnable()
        {
            var d = new ItemEnableDelegate(EnableServerItem);
            //Если кнопка остановить сервер неактивна, искать проблему здесь
            contextMenu.Invoke(d);
        }
            
        void EnableServerItem()
        {
            contextMenu.Items[0].Enabled = true;
        }
        

        void notify1_MouseClick(object sender, MouseEventArgs e)
        {
            if (e.Button != MouseButtons.Right)
                return;
            Point p = MousePosition;
            //contextmenu.Show(p);
            notify1.ContextMenuStrip.Show(p, ToolStripDropDownDirection.AboveRight);
        }

        void FormForTray_Resize(object sender, EventArgs e)            //Прятать в трей при изменении размера
        {
            if (FormWindowState.Minimized == WindowState)
            {                
                Hide();
            }
        } 

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            notify1.Visible = false;
        }

        private void Form1_Shown(object sender, EventArgs e)
        {
            //WindowState = FormWindowState.Minimized;
            if (_success != "ok")
            {
                Visible = false;
                MessageBox.Show(Rm.GetString("FileNotFound") + @": " + _success, ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
                Close();
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            string dir = Directory.GetCurrentDirectory();
            Assembly testass = Assembly.LoadFile(dir + "\\resources\\rs_analizator.dll");

            Type[] typeslist = testass.GetExportedTypes();
            MethodInfo[] methods = typeslist[0].GetMethods();
            var meths = methods.Where(met => met.Name.Contains("Call")).ToList();
            const string ip = "192.168.3.229";  
            const string name = "minsk";
            const string devtype = "rs";
            var pars = new[] {ip, name, devtype};
            var ttt = new object[2];
            ttt[0] = "GetUsers";
            ttt[1] = pars;
            //ttt[2] = name;
            //ttt[3] = devtype;
            object testobj = Activator.CreateInstance(typeslist[0]);
            var df = MakeDynamicFunc(testobj, meths[0]);
            string st = df(ttt);
            
            //string st = meths[0].Invoke(testobj, ttt).ToString();
            //byte[] uni = Encoding.Unicode.GetBytes(str);
            //byte[] asciibytes = Encoding.Convert(Encoding.Unicode, Encoding.GetEncoding("Windows-1251"), uni);
            //string ascii = Encoding.ASCII.GetString(asciibytes);
            //string st = curdir.getlog(ip, "minsk", "t-vips");
            //curdir.getstatus(str);
            //st = st.Replace(';', '\n');
            MessageBox.Show(st);
        }
        public delegate string DynamicFunc(params object[] parameters);

        public static DynamicFunc MakeDynamicFunc(object target, MethodInfo method)
        {
            return par => (string)method.Invoke(target, par);
        }
    }
}
